/****************************************************************************
*
*  ALi (Shanghai) Corporation, All Rights Reserved. 2003 Copyright (C)
*
*  File: win_upgrade_menu.c
*
*  Description: 
*              
*  History:
*      Date        	Author             	Version     	Comment
*      ====        	======        	=======   	=======
*
****************************************************************************/
#include <sys_config.h>
#include <types.h>
#include <basic_types.h>
#include <mediatypes.h>
#include <api/libc/printf.h>
#include <api/libc/string.h>
#include <api/libfs2/fcntl.h>
#include <osal/osal.h>
#include <api/libosd/osd_lib.h>
#include <api/libchunk/chunk.h>
#include <hld/hld_dev.h>

#include "osdobjs_def.h"

#include "string.id"
#include "images.id"
#include "osd_config.h"
#include "osd_rsc.h"
#include "vkey.h"

#include "win_com_menu_define.h"
#include "win_com.h"
#include "menus_root.h"
#include "win_com_popup.h"


#include <api/libfs2/stat.h>
#include <api/libfs2/dirent.h>
#include <api/libfs2/statvfs.h>
#include <api/libfs2/unistd.h>
#include <api/libfs2/stdio.h>

#include <bus/hdmi/m36/hdmi_dev.h>
#include <bus/hdmi/m36/hdmi_api.h>

/*******************************************************************************
* Objects declaration
*******************************************************************************/
#define HDMI_PRINTF(...) //libc_printf

extern CONTAINER g_win_hdmi_factory_test;

extern TEXT_FIELD hdmi_info_name;
extern TEXT_FIELD hdmi_info1;
extern TEXT_FIELD hdmi_info2;
extern TEXT_FIELD hdmi_info3;
extern TEXT_FIELD hdmi_info4;

//#define	CW_L     //256//90
//#define	CW_T     //100//20
#define	CW_W     800    //440
#define	CW_H     460    //300
#define	CW_L     GET_MID_L(CW_W)     //256//90
#define	CW_T     GET_MID_T(CW_H)     //100//20

#define ITEM_H  40

#undef WIN_SH_IDX
#define WIN_SH_IDX	WSTL_DIAG_WIN_8BIT //WSTL_POPUP_WIN_02//WSTL_POP_WIN_01

#undef TXTN_SH_IDX
#define TXTN_SH_IDX WSTL_DIAG_BUTTON_01_8BIT 


#define INFO_TXT_NAME_H 2
#define INFO_TXT_NAME_H1 (INFO_TXT_NAME_H + 50)
#define INFO_TXT_NAME_H2 (INFO_TXT_NAME_H1 + 50)
#define INFO_TXT_NAME_H3 (INFO_TXT_NAME_H2 + 50)
#define INFO_TXT_NAME_H4 (INFO_TXT_NAME_H3 + 50)

static VACTION  hdmi_factest_keymap(POBJECT_HEAD pObj, UINT32 key);
static PRESULT  hdmi_factest_callback(POBJECT_HEAD pObj, VEVENT event, UINT32 param1, UINT32 param2);
static char *hdmi_strcat ( char * dst, const char * src);
///extern UINT8 *get_hdmi_cm_mfc_code(void);
///extern UINT8 *get_hdmi_cm_key_id(void);
extern UINT32 api_program_hdmi_hdcp(UINT8* hdcp_key, UINT32 length);
void hdmi_debug_message_callback(UINT8 message_type, UINT8* message);

UINT16 hdmi_info_name_str[60];
UINT16 hdmi_info1_str[60];
UINT16 hdmi_info2_str[60];
UINT16 hdmi_info3_str[60];
UINT16 hdmi_info4_str[60];

static char    test[60];
static UINT8   Key_id[5];
static last_system_state = SYS_STATE_NORMAL;

#ifdef _CAS9_CA_ENABLE_
const char menuname[] = " ";
//const char version[] = "3602.0201";
//const char code[] = "ALI";
//const char keyid[] = "*****";
#define HDMIVERSION " "
#define HDCPMFCCODE " "
#define CRYPTOMEMORY " "
#define HDCPKEYID   " "
#else
const char menuname[] = "HDMI Factory Test menu";
//const char version[] = "3602.0201";
//const char code[] = "ALI";
//const char keyid[] = "*****";
#define HDMIVERSION " Software Version:  "
#define HDCPMFCCODE " HDCP Manufacturer Code: "
#define CRYPTOMEMORY " Crypto Memory: "
#define HDCPKEYID   " HDCP Key ID:"
#endif

#define LDEF_WIN(varWnd,nxtObj,l,t,w,h,focusID)		\
    DEF_CONTAINER(varWnd,NULL,nxtObj,C_ATTR_ACTIVE,0, \
	    0,0,0,0,0, l,t,w,h, WIN_SH_IDX,WIN_SH_IDX,WIN_SH_IDX,WIN_SH_IDX,   \
	    hdmi_factest_keymap,hdmi_factest_callback,  \
	    nxtObj, focusID,0)

#define LDEF_TXT(root,varTxt,nxtObj,ID,l,t,w,h,resID,str)		\
    DEF_TEXTFIELD(varTxt,root,nxtObj,C_ATTR_ACTIVE,0, \
    ID,ID,ID,ID,ID, l,t,w,h, TXTN_SH_IDX,TXTN_HL_IDX,TXTN_SL_IDX,TXTN_GRY_IDX,   \
    NULL,NULL,  \
    C_ALIGN_LEFT | C_ALIGN_VCENTER, 0,0,resID,str)

#define LDEF_TXT_TITLE(root,varTxt,nxtObj,ID,l,t,w,h,resID,str)		\
    DEF_TEXTFIELD(varTxt,root,nxtObj,C_ATTR_ACTIVE,0, \
    ID,ID,ID,ID,ID, l,t,w,h, TXTN_SH_IDX,TXTN_HL_IDX,TXTN_SL_IDX,TXTN_GRY_IDX,   \
    NULL,NULL,  \
    C_ALIGN_VCENTER | C_ALIGN_VCENTER, 0,0,resID,str)

#define LDEF_LIST_TEXT(root,varNametxt,varTxt1,varTxt2,varTxt3,varTxt4,l,t,w,h)	\
	LDEF_TXT_TITLE(&root,varNametxt,&varTxt1 ,1,l , t + INFO_TXT_NAME_H,w,h,0,hdmi_info_name_str)	\
	LDEF_TXT(&root,varTxt1,&varTxt2 ,2,l , t+INFO_TXT_NAME_H1,w,h,0,hdmi_info1_str)	\
	LDEF_TXT(&root,varTxt2,&varTxt3 ,3,l , t+INFO_TXT_NAME_H2,w,h,0,hdmi_info2_str)	\
	LDEF_TXT(&root,varTxt3,&varTxt4 ,4,l, t+INFO_TXT_NAME_H3,w,h,0,hdmi_info3_str)		\
	LDEF_TXT(&root,varTxt4, NULL ,5,l, t+INFO_TXT_NAME_H4,w,h,0,hdmi_info4_str)	
/*
LDEF_LIST_ITEM(win_info_con,info_item_con,NULL,info_txt_name,info_txt1,info_txt2,\
	CON_L, CON_T + (CON_H + CON_GAP)*0,CON_W,CON_H)
*/
LDEF_LIST_TEXT(g_win_hdmi_factory_test,hdmi_info_name,hdmi_info1,hdmi_info2,hdmi_info3,hdmi_info4,\
    (CW_L+8),CW_T,CW_W-16,ITEM_H);

LDEF_WIN(g_win_hdmi_factory_test,&hdmi_info_name,CW_L,CW_T,CW_W,CW_H,1);

/*******************************************************************************
*	key mapping and event callback definition
*******************************************************************************/

static void hdmi_display_info_set(void)
{

    int     Position;
    UINT8 i;
    
    OSD_SetTextFieldContent(&hdmi_info_name,STRING_ANSI, (UINT32)menuname);

    memset(test,0x00,sizeof(test));
    STRCPY(test,HDMIVERSION); 
    hdmi_strcat(test,get_hdmi_sw_version());
    HDMI_PRINTF("%s\n",get_hdmi_sw_version());
    
    OSD_SetTextFieldContent(&hdmi_info1,STRING_ANSI, (UINT32)test);

    memset(test,0x00,sizeof(test));
    STRCPY(test,HDCPMFCCODE);
    hdmi_strcat(test, get_hdmi_cm_mfc_code());
    
    HDMI_PRINTF("%s\n",get_hdmi_cm_mfc_code());
    OSD_SetTextFieldContent(&hdmi_info2,STRING_ANSI, (UINT32)test);

    memset(test,0x00,sizeof(test));	
    STRCPY(test,CRYPTOMEMORY); 
    hdmi_strcat(test, get_hdmi_cm_status() );	
    OSD_SetTextFieldContent(&hdmi_info3,STRING_ANSI, (UINT32)test); 	
	
    memset(test,0x00,sizeof(test));
    memset(Key_id,0x00,sizeof(Key_id));
    Position = 0;
    Position += sprintf( test+Position,"%s",HDCPKEYID);
    MEMCPY(Key_id,get_hdmi_cm_key_id(),sizeof(Key_id));
    for(i = 0; i < sizeof(Key_id) - 1; i++)
    {
        Position += sprintf(test+Position,"0x%.2x,",Key_id[i]);
        HDMI_PRINTF("0x%.2x,",Key_id[i]);
    }
    Position += sprintf(test+Position,"0x%.2x",Key_id[i]);
    HDMI_PRINTF("0x%.2x",Key_id[i]);
    HDMI_PRINTF("\n");
    OSD_SetTextFieldContent(&hdmi_info4,STRING_ANSI, (UINT32)test);	
    OSD_DrawObject((POBJECT_HEAD )&g_win_hdmi_factory_test,C_UPDATE_ALL);

}
static VACTION  hdmi_factest_keymap(POBJECT_HEAD pObj, UINT32 key)
{
	VACTION act;

	switch(key)
	{
	case V_KEY_EXIT:
		act = VACT_CLOSE;
		break;
	default:
		act = VACT_PASS;
	}

	return act;
}

UINT32 edid_log_file, debug_log_file;

static PRESULT  hdmi_factest_callback(POBJECT_HEAD pObj, VEVENT event, UINT32 param1, UINT32 param2)
{
#ifndef _CAS9_CA_ENABLE_
	struct hdmi_device *hdmi_dev = (struct hdmi_device *)dev_get_by_type(NULL,HLD_DEV_TYPE_HDMI);	
	PRESULT ret = PROC_PASS;
	UINT8 bID;
	POBJECT_HEAD nxtObj;
    POBJECT_HEAD topmenu;
	bID = OSD_GetObjID(pObj);
	extern sys_state_t      system_state; 
	UINT8 buf[512];
	UINT32 v_key, i;
	FILE *fp;
	MULTISEL *pMsel;
	static BOOL log_edid_info = FALSE, log_dbg_info = FALSE,  ignore_hotplug = FALSE;

	switch(event)
	{
    case EVN_PRE_OPEN:
        
        //ap_enable_key_task_get_key(TRUE);
		//key_set_upgrade_check_flag(0);
		last_system_state = system_state;
        //system_state = SYS_STATE_UPGRAGE_HOST;
		memset(hdmi_info_name_str,0x00,sizeof(hdmi_info_name_str));
        memset(hdmi_info1_str,0x00,sizeof(hdmi_info1_str));
        memset(hdmi_info2_str,0x00,sizeof(hdmi_info2_str));
        memset(hdmi_info3_str,0x00,sizeof(hdmi_info3_str));
        memset(hdmi_info4_str,0x00,sizeof(hdmi_info4_str));		
        wincom_close_title();
		if(menu_stack_get(0) == (POBJECT_HEAD)&g_win_mainmenu)
		{
			OSD_ClearObject( (POBJECT_HEAD) &g_win_mainmenu, C_UPDATE_ALL);
			topmenu = menu_stack_get_top();
			if(topmenu)
				OSD_ClearObject( topmenu, C_UPDATE_ALL);
		}
        break;
    case EVN_POST_OPEN:
	    hdmi_dev->io_control(hdmi_dev,HDMI_CMD_REG_CALLBACK, HDMI_CB_DBG_MSG, (UINT32)hdmi_debug_message_callback);        
        hdmi_display_info_set();
        break;
    case EVN_POST_CLOSE:
        if(menu_stack_get(0) == (POBJECT_HEAD)&g_win_mainmenu)
		    OSD_TrackObject( (POBJECT_HEAD) &g_win_mainmenu, C_UPDATE_ALL);	
        system_state = last_system_state;
        break;
	case EVN_UNKNOWN_ACTION:
		break;
	case EVN_UNKNOWNKEY_GOT:
		ap_hk_to_vk(0, param1, &v_key); 
		switch(v_key)
		{		
			case V_KEY_RED: 	// Red Button : Log EDID Information //old IR Red key is 65
				if(log_edid_info == FALSE)
				{
					log_edid_info = TRUE;						
					
					// Check log file exist or not, if exist delete it.
					edid_log_file= fs_open("/c/hdmi_edid_log.txt", O_RDONLY, 0666);
//						if(edid_log_file >= 0)	 /*always is true ,clean the warning */
					{
						fs_close(edid_log_file);
						fs_remove("/c/hdmi_edid_log.txt");
					}

						edid_log_file = fs_open("/c/hdmi_edid_log.txt", O_RDWR | O_CREAT, S_IFREG | S_IRWXU);							
					hdmi_log_edid_start();						
					win_com_popup_open(WIN_POPUP_TYPE_SMSG,"Start to Log EDID Information", 0); 												
				}
				else
				{
					log_edid_info = FALSE;	
					fs_close( edid_log_file );
					fs_sync("/c/"); 		
					hdmi_log_edid_stop();
					win_com_popup_open(WIN_POPUP_TYPE_SMSG,"Stop to Log EDID Information", 0);					
				}
				osal_task_sleep(2000);
				win_compopup_close();					
				hdmi_display_info_set();
				break;	
			case V_KEY_GREEN:		// Green Button : Log debug Information
				if(log_dbg_info == FALSE)
				{
					log_dbg_info = TRUE;						
					
					// Check log file exist or not, if exist delete it.
					debug_log_file= fs_open("/c/hdmi_debug_log.txt", O_RDONLY, 0666);
//						if(debug_log_file >= 0) 	/*always is true ,clean the warning */
					{
						fs_close(debug_log_file);
						fs_remove("/c/hdmi_debug_log.txt");
					}

						debug_log_file = fs_open("/c/hdmi_debug_log.txt", O_RDWR | O_CREAT, S_IFREG | S_IRWXU); 						
					hdmi_log_debug_start(); 					
					win_com_popup_open(WIN_POPUP_TYPE_SMSG,"Start to Log Debug Information", 0);													
				}
				else
				{
					log_dbg_info = FALSE;	
					fs_close( debug_log_file );
					fs_sync("/c/"); 					
					hdmi_log_debug_stop();
					win_com_popup_open(WIN_POPUP_TYPE_SMSG,"Stop to Log Debug Information", 0); 				
				}
				osal_task_sleep(2000);
				win_compopup_close();					
				hdmi_display_info_set();				
				break;
			case V_KEY_YELLOW:		// Yellow Button : Switch on/off HDCP
				if(api_get_hdmi_hdcp_onoff() == TRUE)
				{
					api_set_hdmi_hdcp_onoff(FALSE);
					win_com_popup_open(WIN_POPUP_TYPE_SMSG,"Turn HDCP Off", 0); 
				}
				else
				{
					api_set_hdmi_hdcp_onoff(TRUE);
					win_com_popup_open(WIN_POPUP_TYPE_SMSG,"Turn HDCP On", 0);						
				}										
				osal_task_sleep(2000);
				win_compopup_close();					
				hdmi_display_info_set();						
				break;	
				
			default:
				break;
		}			

	    break;
	}

	return ret;	
#endif	
}

void hdmi_debug_message_callback(UINT8 message_type, UINT8* message)
{
	switch(message_type)
	{
		case 1:
			fs_write(edid_log_file, message, strlen(message));		
			libc_printf(message);		
			break;
		case 2:			
			fs_write(debug_log_file, message, strlen(message));		
			libc_printf(message);
			break;
		default:
			break;
	}

	return;
}
static char *hdmi_strcat ( char * dst, const char * src)
{
        char * cp = dst;
        while( *cp )
                cp++;                   /* find end of dst */
        while( *cp++ = *src++ ) ;       /* Copy src to end of dst */
        return( dst );                  /* return dst */
}

